Snowball_233

Snowball_233

A student who is learning coding.

恢復被 rm 刪除但被進程佔用的文件

發生在上個月一件非常不幸的事情, 在我興高采烈地
準備為我的 Minecraft 伺服器編寫一個菜單系統的時候, 
不知為何, Termius 就將原本想寫的 'cd ./server'
自動補全為 'rm -rf ./server',
但最後還是有驚無險的恢復了 95% 以上的數據.

適用範圍#

  • 文件仍然在快取中運行, 這也意味著在恢復期間,你不能結束該進程或關機.

步驟#

  1. 誤刪文件,但該文件被進程佔用.

    $ rm test.sh
    
  2. 使用 lsof 命令列出已被刪除但仍被進程佔用的文件

    $ lsof | grep -i delete | grep speed
    sh  6567  root  4r  REG  253,0  865  /home/test.sh(deleted)
    
    • 其中,第一項 sh 為進程名,第二項 6567 為進程號
  3. 進入進程目錄

    $ cd /proc/6567/fd
    $ ls -la
    lr-x------. 1 root root 64 July 13 02:10 4 -> /home/test.sh (deleted)
    
    • 其中,第九項 4 為文件描述符
  4. 恢復

    $ cat 4 > /home/test.sh
    

恢復一個文件夾#

  • 若同時被刪除的是一個文件夾,則像這樣的手動恢復太過於繁瑣,特別是在小文件繁多的時候非常棘手,那麼,我們不妨使用一個小程序來進行批量的恢復.

  • 在此之前,您需要把 步驟 1 中所有需要恢復的文件導出為一個 log 文件,這裡並不過多贅述.

    use std::fs;
    use std::io::Read;
    
    fn main() {
        let mut log_file = fs::File::open("/home/deleted_files.log").unwrap(); // 填寫您待恢復的文件列表路徑
        let mut logs = String::new();
        log_file.read_to_string(&mut logs).unwrap();
        let mut command = String::new();
        let mut paths = Vec::new();
    
        let logs = logs.split("\n");
    
        for log in logs {
            let log = log.split_whitespace().collect::<Vec<&str>>();
    
            if log.len() < 12 {
                continue;
            }
    
            let number = log[8]; // 8 為文件描述符所處列數, 根據文件實際情況進行修改
            let path = log[10]; //  10 為文件原始路徑所在列數, 根據文件實際情況進行修改
    
            if !path.starts_with("/home") { // 填寫您恢復至的目標文件夾
                continue;
            }
    
            println!("{}: {}", number, path);
            command.push_str(format!("cat {} > ~/recovery{}\n", number, path).as_str());
    
            let path = path.split("/").collect::<Vec<&str>>();
            let path = path[..path.len() - 1].join("/");
            let path = format!("~/recovery{}", path);
    
            if !paths.contains(&path) {
                paths.push(path);
            }
        }
    
        let mut complete_cmd = String::new();
    
        for path in paths {
            complete_cmd.push_str(format!("mkdir -p {}\n", path).as_str());
        }
    
        println!("{}", complete_cmd);
        complete_cmd.push_str(&command);
    
        fs::write("recovery.sh", complete_cmd).unwrap();
    }
    
  • 最後運行生成好的 recovery.sh 即可恢復全部文件.


注意: 對於 Minecraft 伺服器來說,玩家數據是無法直接恢復的,且本方法不能保證百分百找回全部被刪除的文件,還請各位及時做好文件備份,不要讓後悔成為誤刪的結果!

此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://blog.rescueme.life/posts/devops/restore-files-deleted-by-rm-but-occupied-by-processes


載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。